
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

#include <linux/mod_devicetable.h>
#include <linux/of_device.h>

#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/current.h>



static int sr501_data = 0;
static int major;
static int irq;
static struct class *sr501_class;
static struct gpio_desc *sr501_gpiod;
//static wait_queue_head_t sr501_wq;     
/*配合在probe（）中使用init_waitqueue_head()函数,等同于DECLARE_WAIT_QUEUE_HEAD（）*/


DECLARE_WAIT_QUEUE_HEAD(sr501_wait_queue);							  /*创建并初始化等待队列*/

/**3.1**/
static int sr501_open(struct inode *inode, struct file *file)
{
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;	
}

/**3.2**/
static ssize_t sr501_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int ret;
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	int len;
	len = (size < 4) ? size : 4; 
	wait_event_interruptible(sr501_wait_queue, sr501_data);				/*将进程放入等待队列*/
	ret = copy_to_user(buf, &sr501_data, len);
	sr501_data = 0;
	return len;
}

/*3.3 应用程序使用close（）时调用*/
static int sr501_close(struct inode *inode, struct file *file)
{
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;	
}

/**3**/
static struct file_operations sr501_fops = {
	.owner 	 = THIS_MODULE,
	.open 	 = sr501_open,
	.read 	 = sr501_read,
	.release = sr501_close,
};


/*4.中断处理函数*/
static irqreturn_t sr501_isr(int irq, void *dev_id)
{
	int val = gpiod_get_value(sr501_gpiod);								/*读gpio*/
	sr501_data = 0x80 | val;
	wake_up(&sr501_wait_queue);										/*唤醒等待进程*/
	
	return 	IRQ_HANDLED;
}

/**2.1**/
static int sr501_probe(struct platform_device *pdev)
{
	int ret;
	struct device *udev;
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	sr501_gpiod = gpiod_get(&pdev->dev, NULL, 0);										/*从设备树节点获取gpio*/
	if (IS_ERR(sr501_gpiod))
		printk("gpio get err.\n");
	
	gpiod_direction_input(sr501_gpiod);  												/*设置gpio为输入*/
		
	udev = device_create(sr501_class, NULL, MKDEV(major, 0), NULL, "zmq_sr501");	/*创建设备节点*/
	if (IS_ERR(udev))
		printk("sr501 device_create err\n");
		
	irq = gpiod_to_irq(sr501_gpiod);													/*申请中断号irq*/
	ret = request_irq(irq, sr501_isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "sr501_irq", NULL);					/*注册中断函数*/
	return ret;

}

/*2.2 platform_driver_unregister()函数时调用*/
static int sr501_remove(struct platform_device *dev)
{
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);	
	
	free_irq(irq, NULL);								/*释放中断*/	
	gpiod_put(sr501_gpiod);								/*释放gpio*/	
	device_destroy(sr501_class, MKDEV(major, 0));		/*销毁设备节点*/	
	
	return 0;
}

/*2.3 构造与设备树节点匹配属性*/
static struct of_device_id sr501_of_device_id[] = {
	{ .compatible = "zmq,sr501", },
	{  },	
};

/*2.构造platform_driver结构体*/
static struct platform_driver sr501_platform_drv = {
	.probe  = sr501_probe,
	.remove = sr501_remove,
	.driver = {
		.name = "sr501_drv",
		.of_match_table = sr501_of_device_id,
	},
};



/*1.模块加载入口函数*/
static int sr501_init(void)
{
	int ret;
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);

	
	major = register_chrdev(0, "zmq_sr501_fops", &sr501_fops);		/*注册字符驱动程序，返回主设备号major*/
	
	sr501_class = class_create(THIS_MODULE, "zmq_sr501_class");		/*创建驱动程序的类*/
	if (IS_ERR(sr501_class)) {
		printk("sr501_class create err.\n");
		unregister_chrdev(major, "sr501");
		return PTR_ERR(sr501_class);
	}
	//init_waitqueue_head(&sr501_wait_queue);
	
	ret = platform_driver_register(&sr501_platform_drv);			/*注册platform_driver*/	
	return ret;
}

/*5.模块卸载出口函数*/
static void sr501_exit(void)
{
	printk("%s  %s  line %d\n", __FILE__, __FUNCTION__, __LINE__);
	platform_driver_unregister(&sr501_platform_drv);
	class_destroy(sr501_class);							/*销毁设备类*/															
	unregister_chrdev(major, "zmq_sr501_fops");			/*卸载字符驱动程序*/
}

/**6**/

module_init(sr501_init);
module_exit(sr501_exit);
MODULE_LICENSE("GPL");

